home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / sv_user.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  14KB  |  630 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // sv_user.c -- server code for moving users
  21.  
  22. #include "quakedef.h"
  23.  
  24. edict_t    *sv_player;
  25.  
  26. extern    cvar_t    sv_friction;
  27. cvar_t    sv_edgefriction = {"edgefriction", "2"};
  28. extern    cvar_t    sv_stopspeed;
  29.  
  30. static    vec3_t        forward, right, up;
  31.  
  32. vec3_t    wishdir;
  33. float    wishspeed;
  34.  
  35. // world
  36. float    *angles;
  37. float    *origin;
  38. float    *velocity;
  39.  
  40. qboolean    onground;
  41.  
  42. usercmd_t    cmd;
  43.  
  44. cvar_t    sv_idealpitchscale = {"sv_idealpitchscale","0.8"};
  45.  
  46.  
  47. /*
  48. ===============
  49. SV_SetIdealPitch
  50. ===============
  51. */
  52. #define    MAX_FORWARD    6
  53. void SV_SetIdealPitch (void)
  54. {
  55.     float    angleval, sinval, cosval;
  56.     trace_t    tr;
  57.     vec3_t    top, bottom;
  58.     float    z[MAX_FORWARD];
  59.     int        i, j;
  60.     int        step, dir, steps;
  61.  
  62.     if (!((int)sv_player->v.flags & FL_ONGROUND))
  63.         return;
  64.         
  65.     angleval = sv_player->v.angles[YAW] * M_PI*2 / 360;
  66.     sinval = sin(angleval);
  67.     cosval = cos(angleval);
  68.  
  69.     for (i=0 ; i<MAX_FORWARD ; i++)
  70.     {
  71.         top[0] = sv_player->v.origin[0] + cosval*(i+3)*12;
  72.         top[1] = sv_player->v.origin[1] + sinval*(i+3)*12;
  73.         top[2] = sv_player->v.origin[2] + sv_player->v.view_ofs[2];
  74.         
  75.         bottom[0] = top[0];
  76.         bottom[1] = top[1];
  77.         bottom[2] = top[2] - 160;
  78.         
  79.         tr = SV_Move (top, vec3_origin, vec3_origin, bottom, 1, sv_player);
  80.         if (tr.allsolid)
  81.             return;    // looking at a wall, leave ideal the way is was
  82.  
  83.         if (tr.fraction == 1)
  84.             return;    // near a dropoff
  85.         
  86.         z[i] = top[2] + tr.fraction*(bottom[2]-top[2]);
  87.     }
  88.     
  89.     dir = 0;
  90.     steps = 0;
  91.     for (j=1 ; j<i ; j++)
  92.     {
  93.         step = z[j] - z[j-1];
  94.         if (step > -ON_EPSILON && step < ON_EPSILON)
  95.             continue;
  96.  
  97.         if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) )
  98.             return;        // mixed changes
  99.  
  100.         steps++;    
  101.         dir = step;
  102.     }
  103.     
  104.     if (!dir)
  105.     {
  106.         sv_player->v.idealpitch = 0;
  107.         return;
  108.     }
  109.     
  110.     if (steps < 2)
  111.         return;
  112.     sv_player->v.idealpitch = -dir * sv_idealpitchscale.value;
  113. }
  114.  
  115.  
  116. /*
  117. ==================
  118. SV_UserFriction
  119.  
  120. ==================
  121. */
  122. void SV_UserFriction (void)
  123. {
  124.     float    *vel;
  125.     float    speed, newspeed, control;
  126.     vec3_t    start, stop;
  127.     float    friction;
  128.     trace_t    trace;
  129.     
  130.     vel = velocity;
  131.     
  132.     speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
  133.     if (!speed)
  134.         return;
  135.  
  136. // if the leading edge is over a dropoff, increase friction
  137.     start[0] = stop[0] = origin[0] + vel[0]/speed*16;
  138.     start[1] = stop[1] = origin[1] + vel[1]/speed*16;
  139.     start[2] = origin[2] + sv_player->v.mins[2];
  140.     stop[2] = start[2] - 34;
  141.  
  142.     trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, sv_player);
  143.  
  144.     if (trace.fraction == 1.0)
  145.         friction = sv_friction.value*sv_edgefriction.value;
  146.     else
  147.         friction = sv_friction.value;
  148.  
  149. // apply friction    
  150.     control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
  151.     newspeed = speed - host_frametime*control*friction;
  152.     
  153.     if (newspeed < 0)
  154.         newspeed = 0;
  155.     newspeed /= speed;
  156.  
  157.     vel[0] = vel[0] * newspeed;
  158.     vel[1] = vel[1] * newspeed;
  159.     vel[2] = vel[2] * newspeed;
  160. }
  161.  
  162. /*
  163. ==============
  164. SV_Accelerate
  165. ==============
  166. */
  167. cvar_t    sv_maxspeed = {"sv_maxspeed", "320", false, true};
  168. cvar_t    sv_accelerate = {"sv_accelerate", "10"};
  169. #if 0
  170. void SV_Accelerate (vec3_t wishvel)
  171. {
  172.     int            i;
  173.     float        addspeed, accelspeed;
  174.     vec3_t        pushvec;
  175.  
  176.     if (wishspeed == 0)
  177.         return;
  178.  
  179.     VectorSubtract (wishvel, velocity, pushvec);
  180.     addspeed = VectorNormalize (pushvec);
  181.  
  182.     accelspeed = sv_accelerate.value*host_frametime*addspeed;
  183.     if (accelspeed > addspeed)
  184.         accelspeed = addspeed;
  185.     
  186.     for (i=0 ; i<3 ; i++)
  187.         velocity[i] += accelspeed*pushvec[i];    
  188. }
  189. #endif
  190. void SV_Accelerate (void)
  191. {
  192.     int            i;
  193.     float        addspeed, accelspeed, currentspeed;
  194.  
  195.     currentspeed = DotProduct (velocity, wishdir);
  196.     addspeed = wishspeed - currentspeed;
  197.     if (addspeed <= 0)
  198.         return;
  199.     accelspeed = sv_accelerate.value*host_frametime*wishspeed;
  200.     if (accelspeed > addspeed)
  201.         accelspeed = addspeed;
  202.     
  203.     for (i=0 ; i<3 ; i++)
  204.         velocity[i] += accelspeed*wishdir[i];    
  205. }
  206.  
  207. void SV_AirAccelerate (vec3_t wishveloc)
  208. {
  209.     int            i;
  210.     float        addspeed, wishspd, accelspeed, currentspeed;
  211.         
  212.     wishspd = VectorNormalize (wishveloc);
  213.     if (wishspd > 30)
  214.         wishspd = 30;
  215.     currentspeed = DotProduct (velocity, wishveloc);
  216.     addspeed = wishspd - currentspeed;
  217.     if (addspeed <= 0)
  218.         return;
  219. //    accelspeed = sv_accelerate.value * host_frametime;
  220.     accelspeed = sv_accelerate.value*wishspeed * host_frametime;
  221.     if (accelspeed > addspeed)
  222.         accelspeed = addspeed;
  223.     
  224.     for (i=0 ; i<3 ; i++)
  225.         velocity[i] += accelspeed*wishveloc[i];    
  226. }
  227.  
  228.  
  229. void DropPunchAngle (void)
  230. {
  231.     float    len;
  232.     
  233.     len = VectorNormalize (sv_player->v.punchangle);
  234.     
  235.     len -= 10*host_frametime;
  236.     if (len < 0)
  237.         len = 0;
  238.     VectorScale (sv_player->v.punchangle, len, sv_player->v.punchangle);
  239. }
  240.  
  241. /*
  242. ===================
  243. SV_WaterMove
  244.  
  245. ===================
  246. */
  247. void SV_WaterMove (void)
  248. {
  249.     int        i;
  250.     vec3_t    wishvel;
  251.     float    speed, newspeed, wishspeed, addspeed, accelspeed;
  252.  
  253. //
  254. // user intentions
  255. //
  256.     AngleVectors (sv_player->v.v_angle, forward, right, up);
  257.  
  258.     for (i=0 ; i<3 ; i++)
  259.         wishvel[i] = forward[i]*cmd.forwardmove + right[i]*cmd.sidemove;
  260.  
  261.     if (!cmd.forwardmove && !cmd.sidemove && !cmd.upmove)
  262.         wishvel[2] -= 60;        // drift towards bottom
  263.     else
  264.         wishvel[2] += cmd.upmove;
  265.  
  266.     wishspeed = Length(wishvel);
  267.     if (wishspeed > sv_maxspeed.value)
  268.     {
  269.         VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel);
  270.         wishspeed = sv_maxspeed.value;
  271.     }
  272.     wishspeed *= 0.7;
  273.  
  274. //
  275. // water friction
  276. //
  277.     speed = Length (velocity);
  278.     if (speed)
  279.     {
  280.         newspeed = speed - host_frametime * speed * sv_friction.value;
  281.         if (newspeed < 0)
  282.             newspeed = 0;    
  283.         VectorScale (velocity, newspeed/speed, velocity);
  284.     }
  285.     else
  286.         newspeed = 0;
  287.     
  288. //
  289. // water acceleration
  290. //
  291.     if (!wishspeed)
  292.         return;
  293.  
  294.     addspeed = wishspeed - newspeed;
  295.     if (addspeed <= 0)
  296.         return;
  297.  
  298.     VectorNormalize (wishvel);
  299.     accelspeed = sv_accelerate.value * wishspeed * host_frametime;
  300.     if (accelspeed > addspeed)
  301.         accelspeed = addspeed;
  302.  
  303.     for (i=0 ; i<3 ; i++)
  304.         velocity[i] += accelspeed * wishvel[i];
  305. }
  306.  
  307. void SV_WaterJump (void)
  308. {
  309.     if (sv.time > sv_player->v.teleport_time
  310.     || !sv_player->v.waterlevel)
  311.     {
  312.         sv_player->v.flags = (int)sv_player->v.flags & ~FL_WATERJUMP;
  313.         sv_player->v.teleport_time = 0;
  314.     }
  315.     sv_player->v.velocity[0] = sv_player->v.movedir[0];
  316.     sv_player->v.velocity[1] = sv_player->v.movedir[1];
  317. }
  318.  
  319.  
  320. /*
  321. ===================
  322. SV_AirMove
  323.  
  324. ===================
  325. */
  326. void SV_AirMove (void)
  327. {
  328.     int            i;
  329.     vec3_t        wishvel;
  330.     float        fmove, smove;
  331.  
  332.     AngleVectors (sv_player->v.angles, forward, right, up);
  333.  
  334.     fmove = cmd.forwardmove;
  335.     smove = cmd.sidemove;
  336.     
  337. // hack to not let you back into teleporter
  338.     if (sv.time < sv_player->v.teleport_time && fmove < 0)
  339.         fmove = 0;
  340.         
  341.     for (i=0 ; i<3 ; i++)
  342.         wishvel[i] = forward[i]*fmove + right[i]*smove;
  343.  
  344.     if ( (int)sv_player->v.movetype != MOVETYPE_WALK)
  345.         wishvel[2] = cmd.upmove;
  346.     else
  347.         wishvel[2] = 0;
  348.  
  349.     VectorCopy (wishvel, wishdir);
  350.     wishspeed = VectorNormalize(wishdir);
  351.     if (wishspeed > sv_maxspeed.value)
  352.     {
  353.         VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel);
  354.         wishspeed = sv_maxspeed.value;
  355.     }
  356.     
  357.     if ( sv_player->v.movetype == MOVETYPE_NOCLIP)
  358.     {    // noclip
  359.         VectorCopy (wishvel, velocity);
  360.     }
  361.     else if ( onground )
  362.     {
  363.         SV_UserFriction ();
  364.         SV_Accelerate ();
  365.     }
  366.     else
  367.     {    // not on ground, so little effect on velocity
  368.         SV_AirAccelerate (wishvel);
  369.     }        
  370. }
  371.  
  372. /*
  373. ===================
  374. SV_ClientThink
  375.  
  376. the move fields specify an intended velocity in pix/sec
  377. the angle fields specify an exact angular motion in degrees
  378. ===================
  379. */
  380. void SV_ClientThink (void)
  381. {
  382.     vec3_t        v_angle;
  383.  
  384.     if (sv_player->v.movetype == MOVETYPE_NONE)
  385.         return;
  386.     
  387.     onground = (int)sv_player->v.flags & FL_ONGROUND;
  388.  
  389.     origin = sv_player->v.origin;
  390.     velocity = sv_player->v.velocity;
  391.  
  392.     DropPunchAngle ();
  393.     
  394. //
  395. // if dead, behave differently
  396. //
  397.     if (sv_player->v.health <= 0)
  398.         return;
  399.  
  400. //
  401. // angles
  402. // show 1/3 the pitch angle and all the roll angle
  403.     cmd = host_client->cmd;
  404.     angles = sv_player->v.angles;
  405.     
  406.     VectorAdd (sv_player->v.v_angle, sv_player->v.punchangle, v_angle);
  407.     angles[ROLL] = V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
  408.     if (!sv_player->v.fixangle)
  409.     {
  410.         angles[PITCH] = -v_angle[PITCH]/3;
  411.         angles[YAW] = v_angle[YAW];
  412.     }
  413.  
  414.     if ( (int)sv_player->v.flags & FL_WATERJUMP )
  415.     {
  416.         SV_WaterJump ();
  417.         return;
  418.     }
  419. //
  420. // walk
  421. //
  422.     if ( (sv_player->v.waterlevel >= 2)
  423.     && (sv_player->v.movetype != MOVETYPE_NOCLIP) )
  424.     {
  425.         SV_WaterMove ();
  426.         return;
  427.     }
  428.  
  429.     SV_AirMove ();    
  430. }
  431.  
  432.  
  433. /*
  434. ===================
  435. SV_ReadClientMove
  436. ===================
  437. */
  438. void SV_ReadClientMove (usercmd_t *move)
  439. {
  440.     int        i;
  441.     vec3_t    angle;
  442.     int        bits;
  443.     
  444. // read ping time
  445.     host_client->ping_times[host_client->num_pings%NUM_PING_TIMES]
  446.         = sv.time - MSG_ReadFloat ();
  447.     host_client->num_pings++;
  448.  
  449. // read current angles    
  450.     for (i=0 ; i<3 ; i++)
  451.         angle[i] = MSG_ReadAngle ();
  452.  
  453.     VectorCopy (angle, host_client->edict->v.v_angle);
  454.         
  455. // read movement
  456.     move->forwardmove = MSG_ReadShort ();
  457.     move->sidemove = MSG_ReadShort ();
  458.     move->upmove = MSG_ReadShort ();
  459.     
  460. // read buttons
  461.     bits = MSG_ReadByte ();
  462.     host_client->edict->v.button0 = bits & 1;
  463.     host_client->edict->v.button2 = (bits & 2)>>1;
  464.  
  465.     i = MSG_ReadByte ();
  466.     if (i)
  467.         host_client->edict->v.impulse = i;
  468.  
  469. #ifdef QUAKE2
  470. // read light level
  471.     host_client->edict->v.light_level = MSG_ReadByte ();
  472. #endif
  473. }
  474.  
  475. /*
  476. ===================
  477. SV_ReadClientMessage
  478.  
  479. Returns false if the client should be killed
  480. ===================
  481. */
  482. qboolean SV_ReadClientMessage (void)
  483. {
  484.     int        ret;
  485.     int        cmd;
  486.     char        *s;
  487.     
  488.     do
  489.     {
  490. nextmsg:
  491.         ret = NET_GetMessage (host_client->netconnection);
  492.         if (ret == -1)
  493.         {
  494.             Sys_Printf ("SV_ReadClientMessage: NET_GetMessage failed\n");
  495.             return false;
  496.         }
  497.         if (!ret)
  498.             return true;
  499.                     
  500.         MSG_BeginReading ();
  501.         
  502.         while (1)
  503.         {
  504.             if (!host_client->active)
  505.                 return false;    // a command caused an error
  506.  
  507.             if (msg_badread)
  508.             {
  509.                 Sys_Printf ("SV_ReadClientMessage: badread\n");
  510.                 return false;
  511.             }    
  512.     
  513.             cmd = MSG_ReadChar ();
  514.             
  515.             switch (cmd)
  516.             {
  517.             case -1:
  518.                 goto nextmsg;        // end of message
  519.                 
  520.             default:
  521.                 Sys_Printf ("SV_ReadClientMessage: unknown command char\n");
  522.                 return false;
  523.                             
  524.             case clc_nop:
  525. //                Sys_Printf ("clc_nop\n");
  526.                 break;
  527.                 
  528.             case clc_stringcmd:    
  529.                 s = MSG_ReadString ();
  530.                 if (host_client->privileged)
  531.                     ret = 2;
  532.                 else
  533.                     ret = 0;
  534.                 if (Q_strncasecmp(s, "status", 6) == 0)
  535.                     ret = 1;
  536.                 else if (Q_strncasecmp(s, "god", 3) == 0)
  537.                     ret = 1;
  538.                 else if (Q_strncasecmp(s, "notarget", 8) == 0)
  539.                     ret = 1;
  540.                 else if (Q_strncasecmp(s, "fly", 3) == 0)
  541.                     ret = 1;
  542.                 else if (Q_strncasecmp(s, "name", 4) == 0)
  543.                     ret = 1;
  544.                 else if (Q_strncasecmp(s, "noclip", 6) == 0)
  545.                     ret = 1;
  546.                 else if (Q_strncasecmp(s, "say", 3) == 0)
  547.                     ret = 1;
  548.                 else if (Q_strncasecmp(s, "say_team", 8) == 0)
  549.                     ret = 1;
  550.                 else if (Q_strncasecmp(s, "tell", 4) == 0)
  551.                     ret = 1;
  552.                 else if (Q_strncasecmp(s, "color", 5) == 0)
  553.                     ret = 1;
  554.                 else if (Q_strncasecmp(s, "kill", 4) == 0)
  555.                     ret = 1;
  556.                 else if (Q_strncasecmp(s, "pause", 5) == 0)
  557.                     ret = 1;
  558.                 else if (Q_strncasecmp(s, "spawn", 5) == 0)
  559.                     ret = 1;
  560.                 else if (Q_strncasecmp(s, "begin", 5) == 0)
  561.                     ret = 1;
  562.                 else if (Q_strncasecmp(s, "prespawn", 8) == 0)
  563.                     ret = 1;
  564.                 else if (Q_strncasecmp(s, "kick", 4) == 0)
  565.                     ret = 1;
  566.                 else if (Q_strncasecmp(s, "ping", 4) == 0)
  567.                     ret = 1;
  568.                 else if (Q_strncasecmp(s, "give", 4) == 0)
  569.                     ret = 1;
  570.                 else if (Q_strncasecmp(s, "ban", 3) == 0)
  571.                     ret = 1;
  572.                 if (ret == 2)
  573.                     Cbuf_InsertText (s);
  574.                 else if (ret == 1)
  575.                     Cmd_ExecuteString (s, src_client);
  576.                 else
  577.                     Con_DPrintf("%s tried to %s\n", host_client->name, s);
  578.                 break;
  579.                 
  580.             case clc_disconnect:
  581. //                Sys_Printf ("SV_ReadClientMessage: client disconnected\n");
  582.                 return false;
  583.             
  584.             case clc_move:
  585.                 SV_ReadClientMove (&host_client->cmd);
  586.                 break;
  587.             }
  588.         }
  589.     } while (ret == 1);
  590.     
  591.     return true;
  592. }
  593.  
  594.  
  595. /*
  596. ==================
  597. SV_RunClients
  598. ==================
  599. */
  600. void SV_RunClients (void)
  601. {
  602.     int                i;
  603.     
  604.     for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
  605.     {
  606.         if (!host_client->active)
  607.             continue;
  608.     
  609.         sv_player = host_client->edict;
  610.  
  611.         if (!SV_ReadClientMessage ())
  612.         {
  613.             SV_DropClient (false);    // client misbehaved...
  614.             continue;
  615.         }
  616.  
  617.         if (!host_client->spawned)
  618.         {
  619.         // clear client movement until a new packet is received
  620.             memset (&host_client->cmd, 0, sizeof(host_client->cmd));
  621.             continue;
  622.         }
  623.  
  624. // always pause in single player if in console or menus
  625.         if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
  626.             SV_ClientThink ();
  627.     }
  628. }
  629.  
  630.